<template>
  <div class="comp-multiple-select" :class="layout">
    <template v-if="value && value.length > 0">
      <div
        v-for="(item,i) in (Array.isArray(value)? value : [value])"
        :key="i"
        class="select-item"
      >
        <a-select
          v-model="value[i].value"
          :disabled="disabled"
          :size="size"
          :dropdown-match-select-width="false"
          style="width: 100%;"
          :style="{
            maxWidth: isSingle
              ? isSortable
                ? '135px'
                : '153px'
              : isSortable
              ? '100px'
              : '111px',
          }"
          allow-clear
          @change="
            (value) => {
              onChange(value, i)
            }
          "
        >
          <a-select-option
            v-for="(op, j) in options"
            :key="j"
            :size="size"
            :value="op.value"
            :disabled="
              op.disabled ||
              (op.value !== value[i].value &&
                (valueKeys || []).includes(op.value))
            "
          >
            <div
              class="vis-option"
              :class="
                op.value !== value[i].value &&
                (valueKeys || []).includes(op.value)
                  ? 'disabled'
                  : ''
              "
            >
              {{ op.text }}
            </div>
          </a-select-option>
        </a-select>
        <span v-if="isSortable" class="btn sort-box">
          <a-icon
            class="sort-item"
            :class="{
              active: value[i] && value[i].sort === 'asc',
              disabled: value[i].value === '' || disabled,
            }"
            type="caret-up"
            title="升序"
            @click="sortChange(i, 'asc', value[i].value === '' || disabled)"
          />
          <a-icon
            class="sort-item"
            :class="{
              active: value[i] && value[i].sort === 'desc',
              disabled: value[i].value === '' || disabled,
            }"
            type="caret-down"
            title="降序"
            @click="sortChange(i, 'desc', value[i].value === '' || disabled)"
          />
        </span>

        <a-dropdown
          v-if="formData.isAggr && value[i].func && !disabled"
          placement="bottomCenter"
        >
          <span
            class="btn btn-func"
            :class="{ disabled: value[i].value === '' || disabled }"
          >
            <a-icon type="align-left" title="聚合算法" />
          </span>
          <a-menu v-if="value[i].value !== ''" slot="overlay">
            <a-menu-item
              v-for="(funcName, f) in funcOption"
              :key="f"
              :class="value[i].func === funcName.value ? 'active' : ''"
              @click="funcClick(funcName, i)"
            >
              {{ funcName.text }}
            </a-menu-item>
          </a-menu>
        </a-dropdown>
        <!-- 非聚合模式 -->
        <span v-else class="btn btn-func disabled">
          <a-icon type="align-left" title="聚合算法" />
        </span>
        <a-icon
          v-if="!isSingle"
          class="btn btn-add"
          title="添加"
          :class="{
            disabled: (value && value.length === options.length) || disabled,
          }"
          type="plus"
          @click="
            () => {
              if (!(value && value.length === options.length)) {
                addItem()
              }
            }
          "
        />
        <a-icon
          v-if="!isSingle"
          class="btn btn-delete"
          title="删除"
          :class="{ disabled: (value && value.length == 1) || disabled }"
          type="minus"
          @click="
            () => {
              if (!(value && value.length == 1)) {
                delteItem(i)
              }
            }
          "
        />
      </div>
    </template>
  </div>
</template>
<script lang="ts">
import { Component, Vue, Prop, Watch } from 'vue-property-decorator'
import { isArray, cloneDeep } from 'lodash'
import { KeyValueStore } from '../vueGridLayout/interfate/grid-Item-data-inteface'

const defaultValue = { value: '', sort: '', func: 'sum' }

@Component
export default class MultipleSelect extends Vue {
  funcOption: Array<any> = [
    {
      text: 'sum',
      value: 'sum',
    },
    {
      text: 'avg',
      value: 'avg',
    },
    {
      text: 'max',
      value: 'max',
    },
    {
      text: 'min',
      value: 'min',
    },
    {
      text: 'distinct',
      value: 'distinct',
    },
    {
      text: 'count',
      value: 'count',
    },
  ]
  @Prop({
    type: Boolean,
    default() {
      return false
    },
  })
  disabled!: boolean
  @Prop({
    type: Boolean,
    default() {
      return false
    },
  })
  isSingle!: boolean
  @Prop({
    type: Boolean,
    default() {
      return false
    },
  })
  isSortable!: boolean
  @Prop({
    type: Array,
  })
  value!: Array<any>
  @Prop({
    type: Object,
    default() {
      return {}
    },
  })
  formData!: object

  @Prop({
    type: Array,
    default() {
      return []
    },
  })
  options!: Array<any>
  @Prop({
    type: String,
    default() {
      return 'small'
    },
  })
  size!: string

  @Prop({
    type: String,
    default() {
      return 'vertical' // horizontal | vertical
    },
  })
  layout!: string

  // 只有外部传入的value变化时才有响应，内部改变不响应，所以存一份内部拷贝innerValue
  private innerValue: Array<any> = []
  @Watch('value', { immediate: true })
  private onValueChange(newValue: Array<any>) {
    this.innerValue = newValue
  }

  get valueKeys() {
    /* eslint-disable */
    return this.innerValue.reduce((rec: Array<string>, item: KeyValueStore) => {
      const rec_ = item.value !== '' ? [...rec, item.value] : rec
      return rec_
    }, [])
  }

  get usedKeys(): Array<string> {
    /* eslint-disable */
    const result: Array<string> = isArray((this.formData as any).valueKey)
      ? (this.formData as any).valueKey.reduce(
          (rec: Array<string>, item: KeyValueStore) => {
            const rec_: Array<string> =
              item.value !== '' ? [...rec, item.value] : rec
            return rec_
          },
          []
        )
      : (this.formData as any).valueKey
      ? [(this.formData as any).valueKey]
      : []
    if ((this.formData as any).labelKey !== '') {
      result.push((this.formData as any).labelKey)
    }
    if ((this.formData as any).groupBy !== '') {
      result.push((this.formData as any).groupBy)
    }
    return result
  }
  funcClick(funcName: any, index: number) {
    if (!isArray(this.value) || this.value.length === 0) {
      this.value = [cloneDeep(defaultValue)]
    }
    this.value[index].func = funcName.value
    this.innerValue = this.value
    this.$emit('input', this.value)
    this.$emit('change', this.value)
  }
  sortChange(index: number, sortValue: string, disable: boolean) {
    if (disable) {
      return
    }
    if (!this.value[index]) {
      this.value[index] = cloneDeep(defaultValue)
    }
    if (this.value[index].value === '') {
      return
    }
    this.value.forEach((v) => {
      v.sort = ''
    })
    this.value[index].sort = sortValue
    this.innerValue = this.value
    this.$emit('input', this.value)
    this.$emit('sortChange', this.value) // sortChange影响到其他控件 在外部进行处理
    // this.$emit('change', this.value)
  }
  addItem() {
    this.value.push(cloneDeep(defaultValue))
    this.innerValue = this.value
    this.$emit('input', this.value)
    this.$emit('change', this.value)
  }
  delteItem(index: number) {
    this.value.splice(index, 1)
    this.innerValue = this.value
    this.$emit('input', this.value)
    this.$emit('change', this.value)
  }
  onChange(_value: any, index: number) {
    const value = _value === undefined ? '' : _value
    const filter = this.value.filter((item) => item === value)
    if (filter.length > 1) {
      this.value[index] = cloneDeep(defaultValue)
    }
    this.value[index].value = value
    this.innerValue = this.value
    setTimeout(() => {
      this.$emit('input', this.value)
      this.$emit('change', this.value)
      this.$forceUpdate()
    }, 10)
  }
  onSubChange(value: any) {
    if (value !== '' && !this.value.find((item) => item === value)) {
      this.value.push(value)
    }
    this.$emit('input', this.value)
    this.$emit('change', this.value)
  }
}
</script>
<style lang="less" scoped>
.comp-multiple-select {
  display: flex;
  flex-flow: row wrap;
  width: 100%;

  &.vertial {
    flex-flow: column nowrap;
  }

  .select-item {
    display: flex;
    flex-flow: row nowrap;
    justify-content: flex-start;
    margin-bottom: 8px;
    width: 100%;

    &:first-child {
      margin-top: 8px;
    }

    &:last-child {
      margin-bottom: 0;
    }
  }

  .btn {
    border: 1px solid #eaeaea;
    color: #555;
    cursor: pointer;
    font-size: 13px;
    height: 24px;
    line-height: 24px;
    margin-left: 2px;
    padding: 0 2px;

    &:hover {
      border-color: #5760e6;
      color: #5760e6;
    }

    &.disabled {
      border-color: #eaeaea;
      color: #888;
      cursor: not-allowed;

      &:hover {
        border-color: #eaeaea;
        color: #888;
      }
    }

    &.sort-box {
      border-color: transparent;
      padding: 0;
      width: 16px;

      &:hover {
        border-color: transparent;
        color: #888;
      }
    }

    &.btn-func {
      position: relative;
    }

    .sort-item {
      border: 1px solid #eaeaea;
      color: #888;
      display: inline-block;
      float: left;
      font-size: 10px;
      height: 10px;
      line-height: 10px;
      width: 16px;
      width: 100%;

      &.active {
        color: #333;
      }

      &:hover {
        border-color: #5760e6;
        color: #5760e6;
      }

      &.disabled {
        cursor: not-allowed !important;

        &.active {
          color: #888;
        }

        &:hover {
          border: 1px solid #eaeaea;
          color: #888;
        }
      }

      &:first-child {
        margin-bottom: 2px;
      }
    }
  }
}

.vis-option {
  display: block;
  height: 32px;
  width: 100%;

  &.disabled {
    cursor: not-allowed;
    opacity: 0.5;
  }
}

/deep/ .ant-dropdown-menu-item.active {
  background: rgba(#5760e6, 0.15);
}
</style>
